<html>
<head><meta charset="utf-8"><title>function `errors` clause · t-lang · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/index.html">t-lang</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/function.20.60errors.60.20clause.html">function `errors` clause</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="236201607"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/function%20%60errors%60%20clause/near/236201607" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Iron-E <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/function.20.60errors.60.20clause.html#236201607">(Apr 26 2021 at 16:10)</a>:</h4>
<p>Hi! I was redirected here from the Rust Discord. I read the <a href="https://github.com/rust-lang/rfcs#before-creating-an-rfc">Before creating an RFC</a> section of the RFCs repo to see what steps I should take, and it recommended getting feedback first. </p>
<p>Essentially I'm trying to take some of the ideas from <a href="https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419">this Pre-RFC</a> and expand on them, if there is an interest. My motivation is that it should be easier to notate <code>Error</code>s which might be returned by a function, and we shouldn't have to create custom <code>Error</code> <code>enum</code>s by hand for each combination of <code>Result</code> which may arise. Especially with all the work going on for <code>try</code> blocks, it would be nice to be able to only have to create custom <code>Error</code> types when there is a new kind of error being returned. </p>
<p>I think this could be doable using <code>enum</code>s which are generated from the function signature (so that they are decomposable) which implement <code>From</code> for each variant so that <code>?</code> will continue to work as expected for each <code>Error</code> notated in the function signature. I have a vague example created <a href="https://pastebin.com/bVKNX75U">here</a> to see what this might look like.</p>
<p>I've never contributed to Rust before so this might not be possible, but I'd like to hear some input from someone more experienced (or from other developers in general) to see if this is desirable. If this seems like something that might be of interest I would develop this further, but I didn't want to draft anything too in-depth until I got some feedback.</p>



<a name="236230448"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/function%20%60errors%60%20clause/near/236230448" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/function.20.60errors.60.20clause.html#236230448">(Apr 26 2021 at 19:32)</a>:</h4>
<p>First, beware that this is a highly divisive area.  There are some comments about it in <a href="https://without.boats/blog/why-ok-wrapping/">https://without.boats/blog/why-ok-wrapping/</a> and <a href="https://github.com/rust-lang/rust/issues/70941">https://github.com/rust-lang/rust/issues/70941</a> that might be of interest, if you haven't seen those yet.</p>
<p>From a <em>lang</em> side specifically, there's probably a decent bit of caution around adding anything here.  I wonder if you might want to join some of the <a class="stream" data-stream-id="257204" href="/#narrow/stream/257204-project-error-handling">#project-error-handling</a> discussions?  It's possible that a bunch of these things are best explored as proc macros for a while, before moving to built-in syntax.</p>
<p>(I do think that there are a bunch of cool possibilities here -- personally I've wanted structural enums for a while, <code>match</code>ed by having types annotations in patterns -- but <a href="https://github.com/rust-lang/rfcs/pull/2584#issuecomment-794508491">with my lang hat on</a>, I'm skeptical of broad changes.)</p>



<a name="236230672"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/function%20%60errors%60%20clause/near/236230672" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jane Lusby <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/function.20.60errors.60.20clause.html#236230672">(Apr 26 2021 at 19:33)</a>:</h4>
<p>there's also a couple of crates that already define this kind of workflow</p>



<a name="236230723"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/function%20%60errors%60%20clause/near/236230723" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jane Lusby <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/function.20.60errors.60.20clause.html#236230723">(Apr 26 2021 at 19:34)</a>:</h4>
<p>but so far I've not seen any take off</p>



<a name="236230764"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/function%20%60errors%60%20clause/near/236230764" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jane Lusby <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/function.20.60errors.60.20clause.html#236230764">(Apr 26 2021 at 19:34)</a>:</h4>
<p><a href="https://crates.io/crates/cex">https://crates.io/crates/cex</a></p>



<a name="236230891"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/function%20%60errors%60%20clause/near/236230891" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jane Lusby <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/function.20.60errors.60.20clause.html#236230891">(Apr 26 2021 at 19:35)</a>:</h4>
<p>and I think there are a few internals threads talking about it</p>



<a name="236230892"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/function%20%60errors%60%20clause/near/236230892" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jane Lusby <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/function.20.60errors.60.20clause.html#236230892">(Apr 26 2021 at 19:35)</a>:</h4>
<p><a href="https://internals.rust-lang.org/t/closed-with-a-new-one-checked-exception-simulation-in-rust-2nd-version/9044">https://internals.rust-lang.org/t/closed-with-a-new-one-checked-exception-simulation-in-rust-2nd-version/9044</a></p>



<a name="236231303"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/function%20%60errors%60%20clause/near/236231303" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jane Lusby <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/function.20.60errors.60.20clause.html#236231303">(Apr 26 2021 at 19:39)</a>:</h4>
<p><a href="https://users.rust-lang.org/t/an-essay-of-checked-exceptions-in-rust/57769">https://users.rust-lang.org/t/an-essay-of-checked-exceptions-in-rust/57769</a></p>



<a name="236233318"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/function%20%60errors%60%20clause/near/236233318" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Iron-E <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/function.20.60errors.60.20clause.html#236233318">(Apr 26 2021 at 19:55)</a>:</h4>
<p><span class="user-mention silent" data-user-id="125270">scottmcm</span> <a href="#narrow/stream/213817-t-lang/topic/function.20.60errors.60.20clause/near/236230448">said</a>:</p>
<blockquote>
<p>From a <em>lang</em> side specifically, there's probably a decent bit of caution around adding anything here.  I wonder if you might want to join some of the <a class="stream" data-stream-id="257204" href="/#narrow/stream/257204-project-error-handling">#project-error-handling</a> discussions?  It's possible that a bunch of these things are best explored as proc macros for a while, before moving to built-in syntax.</p>
</blockquote>
<p>I definitely understand the caution around this area, especially since committing to any ideas would change the way that a lot of functions are written. I didn't expect this to be a divisive topic though— thanks for the forewarning!</p>
<p>I personally am not a huge fan of the one-size-fits-all module-level <code>Error</code> types which are applied to many functions, as I have found that they represent a bigger domain of possible <code>Error</code>s than a given function could actually return. This is the biggest argument for something like this, I think: it would allow for much more clarity around what <code>Error</code>s are being returned from which functions.</p>
<p>I also agree with the point that <strong>oooutlk</strong> raises (thank you for that link, <span class="user-mention" data-user-id="220273">@Jane Lusby</span> ) that these errors aren't "infectious" so long as the underlying <code>Error</code> types (that is to say, not the generated <code>enum</code>s) are put in the function clause. I see a lot of potential for misuse in that area, given that it would expose all of the functions which are being called by another function.</p>
<p>I'd love to join the <a class="stream" data-stream-id="257204" href="/#narrow/stream/257204-project-error-handling">#project-error-handling</a> discussions though— should I reference this topic over there?</p>



<a name="236878323"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/function%20%60errors%60%20clause/near/236878323" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Iron-E <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/function.20.60errors.60.20clause.html#236878323">(Apr 30 2021 at 18:11)</a>:</h4>
<p>I did some more work on this over the past few days. I wrote a proc macro (<a href="https://github.com/Iron-E/erro-rs">source</a>) which generates the demo code I wrote.</p>
<p>(Note that <code>impl</code> blocks are not supported yet, but I have an idea for how to get that working. This is also my first proc macro, so it's probably sloppy and I welcome criticisms of it!)</p>
<p>Because proc macros don't know the types of the identifiers they have in scope at the time they are expanded, I couldn't get <code>?</code> to work like I had hoped. This is needed because two <code>Error</code> types do not necessarily implement <code>From</code> for each other, even if they have similar variants; thus <code>?</code> cannot convert between one generated <code>Error</code> type and another since it cannot figure out how to convert between them, even though that conversion does exist through a variant. I wasn't able to generate <code>Into</code> or <code>From</code> for the generated <code>Error</code>s this without knowing all of the generated <code>Error</code>s. Instead tried to make an <code>ok!</code> macro which converted inner <code>Err</code>s to the type of the outer <code>fn</code>:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="c1">// This</span>
<span class="kd">let</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ok</span><span class="o">!</span><span class="p">(</span><span class="nb">Result</span>::<span class="o">&lt;</span><span class="kt">isize</span><span class="p">,</span><span class="w"> </span><span class="n">Foo</span><span class="o">&gt;</span>::<span class="nb">Ok</span><span class="p">(</span><span class="mi">1</span><span class="p">));</span><span class="w"></span>

<span class="c1">// Becomes this</span>
<span class="kd">let</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Result</span>::<span class="o">&lt;</span><span class="kt">isize</span><span class="p">,</span><span class="w"> </span><span class="n">Foo</span><span class="o">&gt;</span>::<span class="nb">Ok</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">  </span><span class="nb">Ok</span><span class="p">(</span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">i</span><span class="p">,</span><span class="w"></span>
<span class="w">  </span><span class="nb">Err</span><span class="p">(</span><span class="n">Foo</span>::<span class="n">VariantA</span><span class="p">(</span><span class="n">e</span><span class="p">))</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">into</span><span class="p">()),</span><span class="w"></span>
<span class="w">  </span><span class="nb">Err</span><span class="p">(</span><span class="n">Foo</span>::<span class="n">VariantB</span><span class="p">(</span><span class="n">e</span><span class="p">))</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">into</span><span class="p">()),</span><span class="w"></span>
<span class="w">  </span><span class="nb">Err</span><span class="p">(</span><span class="n">Foo</span>::<span class="n">VariantC</span><span class="p">(</span><span class="n">e</span><span class="p">))</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">into</span><span class="p">()),</span><span class="w"></span>
<span class="p">};</span><span class="w"></span>
</code></pre></div>
<p>But I would need to be able to know the type which the expression resolves to. I looked very closely at the design of <code>#[cex]</code>, and it gets around this by defining a set of <code>enum</code>s which have shared implementations on them. Then, using one of those <code>enum</code>s based on what gets passed to its <code>Result!</code> macro. This approach works well but leads to requiring a separate <code>#[ty_pat]</code> macro on each <code>match</code> block, or else the <code>enum</code>s wouldn't be readable (as each variant is just <code>_0</code>, <code>_1</code>, and so on). I wanted to be able to generate unique and readable names on the <code>enum</code>s— if anyone has an idea on either how to store the previously generated <code>enum</code>s <code>static</code>ally or get the types of expressions I'd be a happy guy :)</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>